package com.xb;

import com.xb.util.dbUtil;
import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 事务：一组逻辑操作单元,使数据从一种状态变换到另一种状态。
 *
 * 事务处理（事务操作）：保证所有事务都作为一个工作单元来执行，即使出现了故障，都不能改变这种执行方式。
 * 当在一个事务中执行多个操作时，要么所有的事务都被提交(commit)，那么这些修改就永久地保存下来；
 * 要么数据库管理系统将放弃所作的所有修改，整个事务回滚(rollback)到最初状态。
 *
 * 为确保数据库中数据的一致性，数据的操纵应当是离散的成组的逻辑单元：当它全部完成时，数据的一致性可以保持，
 * 而当这个单元中的一部分操作失败，整个事务应全部视为错误，所有从起始点以后的操作应全部回退到开始状态。
 */
public class TransactionTest01 {
    /**
     * 测试案列 在user_table里面的AA 给BB转账100块
     * update user_table set balance = balance - 100 where user = 'AA';
     * update user_table set balance = balance + 100 where user = 'BB';
     */
    @Test
    public void test(){
        /**
         * 从这里可以看出这是一个简单的事务，就是一个A给B转账的事务
         * 但是如果我们转账的时候存在一些问题，比如网络的问题
         */
        String sql1 = "update user_table set balance = balance - 100 where user = ?";
        dbUtil.DclSql02(sql1,"AA");
        //这个时候出现了网络的问题
        System.out.println(1/0);
        //这个时候事务就AA就扣了100而BB却没有增加，但是100确不翼而飞了
        String sql2 = "update user_table set balance = balance + 100 where user = ?";
        dbUtil.DclSql02(sql2,"BB");
        System.out.println("转账成功");
    }
    /**
     * 事务自动提交的情况
     *         1.DDL就会进行自动的事务的提交
     *              这个是程序无法干扰的 默认是自动提交的
     *         2.DML在不设置set auto_commit的时候也会自动提交
     *         3.连接关闭的时候也会出现事务的自动提交
     */
    @Test
    public void testTransaction(){
        Connection connection = null;
        try {
            connection = dbUtil.getConnection();
            connection.setAutoCommit(false);
            String sql1 = "update user_table set balance = balance - 100 where user = ?";
            dbUtil.DmlSqlByTransaction(connection,sql1,"AA");
            //这个时候出现了网络的问题
            System.out.println(1/0);
            //这个时候事务就AA就扣了100而BB却没有增加，但是100确不翼而飞了
            String sql2 = "update user_table set balance = balance + 100 where user = ?";
            dbUtil.DmlSqlByTransaction(connection,sql2,"BB");
            System.out.println("转账成功");
            connection.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                connection.rollback();
                System.out.println("转账失败");
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }finally {
            try {
                connection.setAutoCommit(true); //如果对数据库连接是连接池的话这个连接是需要重新放回数据库连接池的。所以就要修改回本来的状态
            } catch (SQLException e) {
                e.printStackTrace();
            }
            dbUtil.closeConAndPs(connection,null);
        }
    }
}
